package com.wjk.cms.service.impl;

import com.alibaba.fastjson.JSONObject;

import com.wjk.cms.service.WxXcxService;
import com.wjk.cms.util.wx.WxApiUtil;
import com.wjk.cms.util.wx.WxConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.net.ssl.HttpsURLConnection;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class WxXcxServiceImpl implements WxXcxService {
    

    final static String ACCESS_TOKEN_REDIS_KEY_PREFIX = "wx:xcx:scm:";

    final static String ACCESS_TOKEN_REDIS_KEY_SUFFIX = ":access_token";

    final static int ACCESS_TOKEN_EXPIRATION_OFFSET = 120; // 缓存access_token的时候，少缓存一段时间，降低其过期的概率


    @Autowired
    private StringRedisTemplate redisTemplate;




    @Override
    public synchronized String getAccessToken(String channel) {
        // get accessToken from Redis
        String redisKey =  ACCESS_TOKEN_REDIS_KEY_PREFIX + WxConfig.APP_ID() + ACCESS_TOKEN_REDIS_KEY_SUFFIX;
        String accessToken = redisTemplate.opsForValue().get(redisKey);
        // if it's empty then ask a new one from wx and save it to redis and the accessToken local var
        int expiresIn = 0;
        if (StringUtils.isEmpty(accessToken)) {
            try {
                JSONObject newAccessTokenResp = doGetAccessToken(WxConfig.APP_ID(), WxConfig.APP_SECRET());
                accessToken = newAccessTokenResp.getString("access_token");
                expiresIn = newAccessTokenResp.getInteger("expires_in");
                expiresIn -= ACCESS_TOKEN_EXPIRATION_OFFSET;
                expiresIn = expiresIn < 0 ? 0 : expiresIn;
                redisTemplate.opsForValue().set(redisKey, accessToken, expiresIn, TimeUnit.SECONDS);
            } catch (Exception e) {
                log.error("获取微信小程序access_token失败 - " + e.getMessage(), e);
            }
        }
        // return the accessToken
        return accessToken;
    }

    @Override
    public synchronized void forceRefreshAccessToken(String channel) {
        String redisKey =  ACCESS_TOKEN_REDIS_KEY_PREFIX + WxConfig.APP_ID() + ACCESS_TOKEN_REDIS_KEY_SUFFIX;
        String accessToken = null;
        int expiresIn = 0;
        try {
            JSONObject newAccessTokenResp = doGetAccessToken(WxConfig.APP_ID() , WxConfig.APP_SECRET());
            accessToken = newAccessTokenResp.getString("access_token");
            expiresIn = newAccessTokenResp.getInteger("expires_in");
            expiresIn -= ACCESS_TOKEN_EXPIRATION_OFFSET;
            expiresIn = expiresIn < 0 ? 0 : expiresIn;
            redisTemplate.opsForValue().set(redisKey, accessToken, expiresIn, TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("获取微信小程序access_token失败 - " + e.getMessage(), e);
        }
    }

    @Override
    public BufferedImage getUnlimited(String userCode,String channel) {
        try {
            JSONObject params = new JSONObject();
            params.put("scene", userCode);
            params.put("is_hyaline", true);
            params.put("page", "pages/tabbar/homePage/goodsDetail");
            return WxApiUtil.postForImage("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken(channel), params.toString());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取小程序全局唯一后台接口调用凭据（access_token）。
     * <p>
     * auth.getAccessToken
     * <p>
     * GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
     */
    static JSONObject doGetAccessToken(String appid, String secret) throws Exception {
        return WxApiUtil.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret);
    }



    public  JSONObject subscribeMessage(String channel, String touser, String templateId,Map<String, String> data) throws Exception {
        JSONObject json = new JSONObject();
        String accessToken = getAccessToken(channel);
        json.put("touser", touser);
        json.put("template_id", templateId);
        json.put("access_token", accessToken);

        JSONObject dataJson = new JSONObject();
        for (Map.Entry<String, String> entry : data.entrySet()) {
            JSONObject keywordJson = new JSONObject();
            keywordJson.put("value", entry.getValue());
            dataJson.put(entry.getKey(), keywordJson);
        }
        json.put("data", dataJson);
        return WxApiUtil.post("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken, json.toString());
    }


    public  JSONObject imgCheck(File file, String channel){
        //返回结果
        JSONObject jsonObject = new JSONObject();
        String result = null;
        try {
            String urlString = "https://api.weixin.qq.com/wxa/img_sec_check?access_token="+getAccessToken(channel);
            URL url = new URL(urlString);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setRequestMethod("POST");//以POST方式提交表单
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);//POST方式不能使用缓存
            //设置请求头信息
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Charset", "UTF-8");
            //设置边界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
            //请求正文信息
            //第一部分
            StringBuilder sb = new StringBuilder();
            sb.append("--");//必须多两条道
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"media\"; filename=\"" + file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");
//            System.out.println("sb:" + sb);

            //获得输出流
            OutputStream out = new DataOutputStream(conn.getOutputStream());
            //输出表头
            out.write(sb.toString().getBytes("UTF-8"));
            //文件正文部分
            //把文件以流的方式 推送道URL中
            DataInputStream din = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] buffer = new byte[1024];
            while ((bytes = din.read(buffer)) != -1) {
                out.write(buffer, 0, bytes);
            }
            din.close();
            //结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("UTF-8");//定义数据最后分割线
            out.write(foot);
            out.flush();
            out.close();
            if (HttpsURLConnection.HTTP_OK == conn.getResponseCode()) {
                StringBuffer strbuffer = null;
                BufferedReader reader = null;
                try {
                    strbuffer = new StringBuffer();
                    reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String lineString = null;
                    while ((lineString = reader.readLine()) != null) {
                        strbuffer.append(lineString);

                    }
                    if (result == null) {
                        result = strbuffer.toString();
//                        System.out.println("result:" + result);
                    }
                } catch (IOException e) {
                    System.out.println("发送POST请求出现异常！" + e);
                    e.printStackTrace();
                } finally {
                    if (reader != null) {
                        reader.close();
                    }
                }

            }
            jsonObject = JSONObject.parseObject(result);
//            log.info("图片检测结果："+result);
        } catch (Exception e) {
            e.printStackTrace();
            jsonObject.put("errCode",500);
            jsonObject.put("errMsg","img_sec_chek调用异常");
        }
        return  jsonObject;
    }
}
